﻿using DongFangGuoKai.WMSPlatform.Core;
using DongFangGuoKai.WMSPlatform.Domain.Models;
using DongFangGuoKai.WMSPlatform.Service.Permissions.DTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;

namespace DongFangGuoKai.WMSPlatform.Service.Permissions
{
    public partial class PermissionService : IPermissionService
    {
        private readonly Repository<t_MenuAction> menuactionrepost;
        private readonly Repository<t_Menu> menurepost;
        private readonly Repository<t_RoleMenuAction> roleMenuActionrepost;
        private readonly Repository<t_Action> actionrepost;
        private readonly Repository<t_UserRole> userrolerepost;
        private readonly Repository<t_Role> rolerepost;
        private readonly Repository<t_RoleWarehouse> rolewarehouserepost;

        public PermissionService(Repository<t_MenuAction> menuactionrepost
            )
        {
            this.menuactionrepost = menuactionrepost;
            menurepost = menuactionrepost.ChangeRepository<Repository<t_Menu>>();
            roleMenuActionrepost = menuactionrepost.ChangeRepository<Repository<t_RoleMenuAction>>();
            actionrepost = menuactionrepost.ChangeRepository<Repository<t_Action>>();
            userrolerepost = menuactionrepost.ChangeRepository<Repository<t_UserRole>>();
            rolerepost = menuactionrepost.ChangeRepository<Repository<t_Role>>();
            rolewarehouserepost = menuactionrepost.ChangeRepository<Repository<t_RoleWarehouse>>();
        }

        /// <summary>
        /// 添加菜单操作关系
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool AddMenuAction(TMenuActionDTO m)
        {
            try
            {
                menuactionrepost.AsTenant().BeginTran();
                var menuaction = menuactionrepost.GetList(m => m.MenuId == m.MenuId);
                if (menuaction != null)
                {
                    if (!menuactionrepost.Delete(menuaction))
                    {
                        menuactionrepost.AsTenant().RollbackTran();
                        return false;
                    }
                }
                if (string.IsNullOrEmpty(m.ActionIds))
                {
                    var mobj = menuactionrepost.GetFirst(x => x.MenuId == m.MenuId);
                    if (mobj != null)
                    {
                        if (menuactionrepost.Delete(mobj))
                        {
                            menuactionrepost.AsTenant().RollbackTran();
                            return true;
                        }

                    }
                    menuactionrepost.AsTenant().RollbackTran();
                    return false;
                }
                foreach (var menu in m.ActionIds.Split(','))
                {
                    t_MenuAction ma = new t_MenuAction();
                    ma.MenuId = m.MenuId;
                    ma.ActionId = Convert.ToInt32(menu);
                    if (!menuactionrepost.Insert(ma))
                    {
                        menuactionrepost.AsTenant().RollbackTran();
                        return false;
                    }
                }
                menuactionrepost.AsTenant().CommitTran();
                return true;
            }
            catch (Exception)
            {
                menuactionrepost.AsTenant().RollbackTran();
                return false;
                throw;
            }
        }

        /// <summary>
        /// 删除菜单
        /// </summary>
        /// <param name="mid"></param>
        /// <returns></returns>
        public bool DelMenuItem(int mid)
        {
            try
            {
                menuactionrepost.AsTenant().BeginTran();
                //判断菜单表是否为空
                var mobj = menurepost.GetFirst(m=>m.Id == mid);
                if (mobj != null)
                {
                    //删除菜单
                    if (!menurepost.Delete(mobj))
                    {
                        menuactionrepost.AsTenant().RollbackTran();
                        return false;
                    }
                    //查询角色菜单操作中该角色拥有的所有权限并删除
                    var rma = roleMenuActionrepost.GetList(x => x.MenuId == mid);
                    if (!roleMenuActionrepost.Delete(rma))
                    {
                        menuactionrepost.AsTenant().RollbackTran();
                        return false;
                    }
                    //查询菜单操作关系表并删除
                    var rw = menuactionrepost.GetList(x => x.MenuId == mid);
                    if (!menuactionrepost.Delete(rw))
                    {
                        menuactionrepost.AsTenant().RollbackTran();
                        return false;
                    }
                    menuactionrepost.AsTenant().CommitTran();
                    return true;
                }
                return false;
            }
            catch (Exception)
            {
                menuactionrepost.AsTenant().RollbackTran();
                return false;
                throw;
            }
        }

        /// <summary>
        /// 分配权限列表显示
        /// </summary>
        /// <param name="rid"></param>
        /// <returns></returns>
        public List<MenuRoleMenuActionDto> GetMenuActionList(int rid)
        {
            //所有菜单
            var mlist = menurepost.GetList();
            //角色菜单按钮关系
            var rmalist = roleMenuActionrepost.GetList();
            //菜单和按钮的关系
            var malist = menuactionrepost.GetList();
            //所有按钮
            var alist = actionrepost.GetList();

            //递归获取所有菜单
            return GetMenuDtoList(mlist.ToList(), malist.ToList(), alist.ToList(), rmalist.ToList(), 0, rid);
        }

        #region 递归菜单
        /// <summary>
        /// 递归获取所有菜单
        /// </summary>
        /// <param name="list">菜单列表</param>
        /// <param name="malist">菜单按钮表</param>
        /// <param name="alist">按钮表</param>
        /// <param name="rmalist">角色菜单按钮关系表</param>
        /// <param name="pid">父级Id</param>
        /// <param name="rid">角色Id</param>
        /// <returns></returns>
        public static List<MenuRoleMenuActionDto> GetMenuDtoList(List<t_Menu> list, List<t_MenuAction> malist, List<t_Action> alist, List<t_RoleMenuAction> rmalist, int pid, int rid)
        {
            var menuDtoList = new List<MenuRoleMenuActionDto>();

            foreach (var menu in list.Where(x => x.ParentId == pid))
            {
                var menuDto = new MenuRoleMenuActionDto
                {
                    //Id
                    id = menu.Id,
                    //父级Id
                    ParentId = menu.ParentId,
                    //路径
                    MenuUrl = menu.MenuUrl,
                    Meta = new MetaDto
                    {
                        //菜单名称
                        MenuName = menu.MenuName,
                        //菜单图标
                        MenuIcon = menu.MenuIcon,
                    },
                    //状态
                    Status = menu.Status,
                    //排序编号
                    DisplayOrder = menu.DisplayOrder
                };

                var children = GetMenuDtoList(list, malist, alist, rmalist, menu.Id, rid);

                if (children.Count > 0)
                {
                    menuDto.children = children;
                }
                else
                {
                    var actionDtoList = GetActionDtoList(malist, alist, menu.Id, rmalist, rid);

                    if (actionDtoList.Count > 0)
                    {
                        menuDto.Action = actionDtoList;
                    }
                }

                menuDto.IsChecked = GetRoleMenuDtoList(rmalist, rid, menu.Id);

                menuDtoList.Add(menuDto);
            }

            return menuDtoList.OrderBy(x => x.DisplayOrder).ToList();
        }

        /// <summary>
        /// 递归获取该菜单所拥有的按钮
        /// </summary>
        /// <param name="malist">菜单按钮表</param>
        /// <param name="alist">按钮表</param>
        /// <param name="mid">菜单Id</param>
        /// <param name="rmalist">角色菜单按钮关系表</param>
        /// <param name="rid">角色Id</param>
        /// <returns></returns>
        public static List<ActionDto> GetActionDtoList(List<t_MenuAction> malist, List<t_Action> alist, int mid, List<t_RoleMenuAction> rmalist, int rid)
        {
            var actionDtoList = new List<ActionDto>();

            foreach (var menuAction in malist.Where(x => x.MenuId == mid))
            {
                var action = alist.FirstOrDefault(x => x.Id == menuAction.ActionId);

                if (action != null)
                {
                    actionDtoList.Add(new ActionDto
                    {
                        Id = action.Id,
                        ActionName = action.ActionName,
                        IsChecked = GetRoleActionDtoList(rmalist, rid, mid, action.Id)
                    });
                }
            }

            return actionDtoList;
        }

        /// <summary>
        /// 判断该角色在该菜单中是否拥有按钮权限
        /// </summary>
        /// <param name="rmalist">角色菜单按钮关系表</param>
        /// <param name="rid">角色Id</param>
        /// <param name="mid">菜单Id</param>
        /// <param name="aid">按钮Id</param>
        /// <returns></returns>
        public static bool GetRoleActionDtoList(List<t_RoleMenuAction> rmalist, int rid, int mid, int aid)
        {
            return rmalist.Any(x => x.RoleId == rid && x.MenuId == mid && x.ActionId == aid);
        }

        /// <summary>
        /// 判断该角色是否拥有该菜单权限
        /// </summary>
        /// <param name="rmalist">角色菜单按钮关系表</param>
        /// <param name="rid">角色Id</param>
        /// <param name="mid">菜单Id</param>
        /// <returns></returns>
        public static bool GetRoleMenuDtoList(List<t_RoleMenuAction> rmalist, int rid, int mid)
        {
            return rmalist.Any(x => x.RoleId == rid && x.MenuId == mid);
        }



        #endregion

        /// <summary>
        /// 分配权限
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public bool AddRoleMenuAction(CRoleMenuAction m)
        {
            try
            {
                menuactionrepost.AsTenant().BeginTran();
                var rmalist = roleMenuActionrepost.GetList(r => r.RoleId == m.Rid);

                if (rmalist.Any())
                {
                    if (!roleMenuActionrepost.Delete(rmalist))
                    {
                        menuactionrepost.AsTenant().RollbackTran();
                        return false;
                    }
                }

                foreach (var item in m.MidArr)
                {
                    var actionIds = item.Aids.Split(',').Select(aid => Convert.ToInt32(aid));

                    foreach (var actionId in actionIds)
                    {
                        var rma = new t_RoleMenuAction
                        {
                            RoleId = m.Rid,
                            MenuId = item.Mid,
                            ActionId = actionId
                        };
                        if (roleMenuActionrepost.Insert(rma) == null)
                        {
                            menuactionrepost.AsTenant().RollbackTran();
                            return false;
                        }
                    }
                }
                menuactionrepost.AsTenant().CommitTran();
                return true;
            }
            catch (Exception)
            {
                menuactionrepost.AsTenant().RollbackTran();
                return false;
                throw;
            }
            
        }

        /// <summary>
        /// 根据用户id查询该用户的所有权限
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public List<UserRoleMenuAction> GetMenuitemAction(int uid)
        {
            var urlist = userrolerepost.GetList(u=>u.UserId == uid).Select(x => x.RoleId).Distinct();

            var rmalist = roleMenuActionrepost.GetList();

            var list = (from ur in urlist
                        join rma in rmalist
                        on ur equals rma.RoleId
                        group rma by rma.MenuId into g
                        select new UserRoleMenuAction
                        {
                            mid = g.Key,
                            aids = g.Select(x => x.ActionId).ToList()
                        }).ToList();

            return list;
        }
    }
}
